package com.example.administrator.myview.util;

import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v4.content.FileProvider;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.example.administrator.myview.BuildConfig;
import com.example.administrator.myview.R;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 检查软件版本，并提示升级，下载安装
 * @author 许润华
 *
 */
public class CheckSoftUpdate {

	private static final int UPDATE_CHECK_ERR 	= -1;	//检查更新失败
	private static final int UPDATE_CHECK_NO 	= 0;	//检查无更新
	private static final int UPDATE_CHECK_YES 	= 1;	//检查有更新
	
	private static final int DOWNLOADING		= 1;	//下载中
	private static final int DOWNLOAD_FINISH 	= 2;	//下载结束
	private static final int DOWNLOAD_ERROR 	= 3;	//下载失败
	private static final int DOWNLOAD_CANCEL 	= 4;	//下载取消
	
	private String mSavePath;							//下载保存路径
	private String apkName = "";						//apk包名称
	private int progress;								//记录进度条数量
	private boolean cancelUpdate = false;				//是否取消更新
	private int versionCurCode = 0;						//当前程序Build号
	private String versionName = "1.0";					//服务器版本号
	private int versionCode = 0;						//服务器Build号
	private boolean MustUpdate = false;					//是否必须升级
	private String UpdateLog = "";						//更新记录列表
	private boolean AppIsOver = false;					//如果最小升级版本>=当前版本，说明这个app已经完蛋，不可再使用！

	private AlertDialog dlgUpdate;						//更新对话框
	private ProgressBar mProgress;						//更新进度条
	
	private Context mContext = null;						//调用窗体句柄
	private OnNextStepListener mOnNextStepListener = null;	//定时监听事件

	/**
	 * 检测软件更新
	 * @param context	调用窗体句柄
	 */
	public CheckSoftUpdate(Context context) {
		mContext = context;
	}
	
	/**
	 * 调用（设置回调）
	 * @param l	回调接口
	 */
	public void CheckUpdate(OnNextStepListener l) {
		//获取包名和版本号
		apkName = getPackageName(mContext)+".apk";
		versionCurCode = getVersionCode(mContext);	//当前程序Build号
		
		//设置事件
		mOnNextStepListener = l;
		
		//启动新线程检查更新
		new updateThread().start();
	}

	/**
	 * 定义回调接口
	 */
    public interface OnNextStepListener {
        void EnterNextStep(); //更新完或者选择某个操作后下一步动作
    }
	
    /**
     * 检查更新线程
     */
	private class updateThread extends Thread {
		@Override
		public void run() {
			//检查是否有更新
			int iResult = UPDATE_CHECK_NO;	
			int verCode = getServerVersionCode();
			if (verCode<0) iResult = UPDATE_CHECK_ERR;
			else if (verCode > getVersionCode(mContext)) iResult = UPDATE_CHECK_YES;
			mUpdateHandler.sendEmptyMessage(iResult);
		}
	}
	
	/**
	 * 得到远程配置信息文件
	 * @param url	配置文件地址
	 * @return		返回文件内容
	 */
    private String getConfigFileFromUrl(String url) {
        String xml = null;
        HttpGet httpget = new HttpGet(url);
        try {
			DefaultHttpClient httpClient = new DefaultHttpClient();
            httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 3000);
            httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
            HttpResponse httpResponse = httpClient.execute(httpget);
            HttpEntity httpEntity = httpResponse.getEntity();
            xml = EntityUtils.toString(httpEntity,"utf-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return xml;
    }
    
    /**
     * 获取版本号，是否必须升级，更新日志
     * @return	返回服务器版本号
     */
	private int getServerVersionCode() {
		int verServerCode = -1;
		
	    // node keys
	    String KEY_NAME = "name";
	    String KEY_VERSION = "version";
	    String KEY_BUILD = "build";
	    String KEY_MUST = "mustMinVer";
	    String KEY_LOG = "log";

	    try {
	         String str = getConfigFileFromUrl("版本更新地址");
	        if (str.length()>0) {
	            try {
	            	if (!str.substring(0, 1).equals("{")) str = str.substring(1);	//2.x系统解析不了
	            	JSONObject obj = new JSONObject(str); 
	            	if (obj.has("appList")&&obj.getString("appList").length()>0) {
	            		JSONArray jsonArray = obj.getJSONArray("appList"); 
	                    for(int i=0;i<jsonArray.length();i++){ 
	                        JSONObject obj2 = (JSONObject)jsonArray.opt(i);
	                        if (obj2.has("name")&&obj2.getString("name").length()>0) {
						        if (obj2.getString(KEY_NAME).toLowerCase().equals(getPackageName(mContext).toLowerCase())) {
						        	versionName = obj2.getString(KEY_VERSION);
						        	try {
						        		verServerCode = Integer.parseInt(obj2.getString(KEY_BUILD));
						        	} catch (Exception ex) {
						        		ex.printStackTrace();
						        	}
									try {
										AppIsOver = Integer.parseInt(obj2.getString(KEY_MUST))>Integer.parseInt(obj2.getString(KEY_BUILD));
									} catch (Exception e) {
										AppIsOver = false;
										e.printStackTrace();
									}
						        	try {
										MustUpdate = versionCurCode < Integer.parseInt(obj2.getString(KEY_MUST));
						        	} catch (Exception e) {
						        		MustUpdate = false;
						        		e.printStackTrace();
						        	}
							        UpdateLog = obj2.getString(KEY_LOG);
							        break;
						        }
	                        }
	                    }
	            	}
		        } catch (JSONException e) {
		            e.printStackTrace();
		        } 
	        }
	    } catch(Exception e) {
	    	e.printStackTrace();
	    }
	    
        versionCode = verServerCode;
		return verServerCode;
	}
	
	/**
	 * 更新线程
	 */
	@SuppressLint("HandlerLeak")
    private Handler mUpdateHandler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
				case UPDATE_CHECK_YES:	//有更新
					DisplayUpdateDialog();	//显示提示对话框，确认下载
					break;
	
				case UPDATE_CHECK_NO:	//无更新				
					if (BuildConfig.DEBUG)	Toast.makeText(mContext,"无更新", Toast.LENGTH_SHORT).show();		//已经是最新版本
					if (mOnNextStepListener!=null) {
						mOnNextStepListener.EnterNextStep();	//检查完更新下一步动作：如果有自动登录则登录否则进入主界面？	
					}
					break;
					
				case UPDATE_CHECK_ERR: //检查更新失败
					if (BuildConfig.DEBUG)	Toast.makeText(mContext, "更新失败", Toast.LENGTH_LONG).show();		//检查更新失败
					if (mOnNextStepListener!=null) {
						mOnNextStepListener.EnterNextStep();	//检查完更新下一步动作：如果有自动登录则登录否则进入主界面？	
					}
    	            break;
					
				default:
					break;
			}
		}
	};	

	/**
	 * 获取软件包名称
	 * @param context	调用窗体句柄
	 * @return			返回软件包名
	 */
	private String getPackageName(Context context) {
		String verName = "1.0";
		try {
			verName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).packageName;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return verName;
	}

	/**
	 * 获取软件版本名称
	 * @param context	调用窗体句柄
	 * @return			返回软件版本
	 */
	private int getVersionCode(Context context) {
		int versionCode = 1;
		try {
			versionCode = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode;
		} catch (NameNotFoundException e) {
			e.printStackTrace();
		}
		return versionCode;
	}
	
	/**
	 * 显示更新对话框
	 */
	private void DisplayUpdateDialog() {
		//控件句柄
		View layout = LayoutInflater.from(mContext).inflate(R.layout.dialog_soft_update, null);
		Button btnExit = (Button) layout.findViewById(R.id.btnExit);
		Button btnUpdate = (Button) layout.findViewById(R.id.btnUpdate);
		Button btnCancel = (Button) layout.findViewById(R.id.btnCancel);
		final LinearLayout layButton = (LinearLayout) layout.findViewById(R.id.layButton);
		final LinearLayout layProgress = (LinearLayout) layout.findViewById(R.id.layProgress);
		layProgress.setVisibility(View.GONE);
		mProgress = (ProgressBar) layout.findViewById(R.id.pbUpdate);
		
		//显示对话框
		dlgUpdate = new AlertDialog.Builder(mContext).create();
		dlgUpdate.setCanceledOnTouchOutside(false);
		
		//标题
		TextView tvTitle = (TextView) layout.findViewById(R.id.tvTitle);
		tvTitle.setText(String.format("标题", versionName));
		
		//Build日期
		TextView tvBuild = (TextView) layout.findViewById(R.id.tvBuild);
		tvBuild.setText(String.format("日期", versionCode));
		
		//更新日志
		TextView tvUpdateLog = (TextView) layout.findViewById(R.id.tvUpdateLog);
		tvUpdateLog.setText(UpdateLog);
		
		//必须更新
		TextView tvMustHint = (TextView) layout.findViewById(R.id.tvMustHint);
		if (AppIsOver) {
			btnExit.setText("必须更新");
			btnUpdate.setVisibility(View.GONE);
			tvMustHint.setText("");
			tvMustHint.setVisibility(View.VISIBLE);
		} else {
			if (MustUpdate) {
				tvMustHint.setText("");
				tvMustHint.setVisibility(View.VISIBLE);
				btnExit.setText("");
			} else {
				tvMustHint.setVisibility(View.GONE);
				btnExit.setText("");
			}
		}

		//退出/忽略
		btnExit.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				if (MustUpdate) System.exit(0);	//必须更新的只有退出
				else {
					dlgUpdate.dismiss();	//下次更新
					if (mOnNextStepListener!=null) {
						mOnNextStepListener.EnterNextStep();	//检查完更新下一步动作：如果有自动登录则登录否则进入主界面？	
					}
				}
			}
		});

		//升级
		btnUpdate.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				layButton.setVisibility(View.GONE);
				layProgress.setVisibility(View.VISIBLE);
				new downloadApkThread().start();	//启动新线程下载软件
			}
		});
		
		//取消更新
		btnCancel.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				dlgUpdate.dismiss();	//隐藏是否更新对话框
				cancelUpdate = true;	//设置取消状态
				mDownHandler.sendEmptyMessage(DOWNLOAD_CANCEL);	//下载取消
			}
		});

		//显示对话框
		dlgUpdate.setCancelable(false);
		dlgUpdate.show();

		//设置大小位置
		if (dlgUpdate.getWindow() != null) {
			dlgUpdate.getWindow().setLayout(mContext.getResources().getDisplayMetrics().widthPixels - (int)
                    (mContext.getResources().getDimension(R.dimen.text_size)),
                    (int) (mContext.getResources().getDimension(R.dimen.text_size)));
			dlgUpdate.getWindow().setContentView(layout);
		}
	}

	/**
	 * 下载线程
	 */
	@SuppressLint("HandlerLeak")
    private Handler mDownHandler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
				case DOWNLOADING:	//正在下载
					mProgress.setProgress(progress);	//设置进度条位置
					break;
					
				case DOWNLOAD_FINISH:	//下载完成
					installApk();	//安装文件
					break;

				case DOWNLOAD_ERROR:	//下载失败
		            Toast.makeText(mContext,"下载失败", Toast.LENGTH_LONG).show();	//"下载安装包失败"
		            if (mOnNextStepListener!=null) {
		            	mOnNextStepListener.EnterNextStep();	//检查完更新下一步动作：如果有自动登录则登录否则进入主界面？	
		            }
					break;
					
				case DOWNLOAD_CANCEL:	//下载取消
					if (MustUpdate) System.exit(0);
					else if (mOnNextStepListener!=null) {
						mOnNextStepListener.EnterNextStep();	//检查完更新下一步动作：如果有自动登录则登录否则进入主界面？	
					}
					break;
					
				default:
					break;
			}
		}
	};
	
	/**
	 * 下载文件线程
	 */
	private class downloadApkThread extends Thread {
		@Override
		public void run() {
			try {
				// 判断SD卡是否存在，并且是否具有读写权限
				if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
					//获得存储卡的路径
					mSavePath = Environment.getExternalStorageDirectory() + "/Download/";
					File dir = new File(mSavePath);
					if(!dir.exists()) dir.mkdirs();	//没有目录就创建
					//创建连接
					String sDownFile;
					if (MyUtils.getMetaValue(mContext, "BaiduMobAd_CHANNEL").equals("2298com")) {    //官方渠道
						sDownFile ="下载地址"+".apk";
					} else {
						sDownFile = "下载地址"+MyUtils.getMetaValue(mContext, "BaiduMobAd_CHANNEL")+".apk";
					}
					URL url = new URL(sDownFile);	//包名和渠道有关
					HttpURLConnection conn = (HttpURLConnection) url.openConnection();
					conn.connect();
					int length = conn.getContentLength();	//获取文件大小
					if (!MyUtils.getMetaValue(mContext, "BaiduMobAd_CHANNEL").equals("2298com") && length<0) {	//当前第三方渠道包文件不存在，下载官方版本
						url = new URL("下载地址"+".apk");
						conn = (HttpURLConnection) url.openConnection();
						conn.connect();
						length = conn.getContentLength();	//获取文件大小
					}
					InputStream is = conn.getInputStream();	//创建输入流
					File apkFile = new File(mSavePath, apkName);
					FileOutputStream fos = new FileOutputStream(apkFile);
					int count = 0;
					byte buf[] = new byte[1024];	//缓存
					// 写入到文件中
					do {
						if (BuildConfig.DEBUG) {	//测试延时下，看到滚动条，并且可以取消
		                    try {
								Thread.currentThread();
								Thread.sleep(5);
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
						}
						
						int numread = is.read(buf);
						count += numread;
						progress = (int) (((float) count / length) * 100);	//计算进度条位置
						mDownHandler.sendEmptyMessage(DOWNLOADING);		//更新进度
						if (numread <= 0) {
							mDownHandler.sendEmptyMessage(DOWNLOAD_FINISH);	// 下载完成
							break;
						}
						fos.write(buf, 0, numread);	//写入文件
					} while (!cancelUpdate);	//点击取消就停止下载.
					fos.close();
					is.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
				mDownHandler.sendEmptyMessage(DOWNLOAD_ERROR);
			}
			// 取消下载对话框显示
			dlgUpdate.dismiss();
		}
	}

	/**
	 * 安装APK文件
	 */
	private void installApk() {
		File apkfile = new File(mSavePath, apkName);
		if (!apkfile.exists()) return;
		//通过Intent安装APK文件
		Intent i = new Intent(Intent.ACTION_VIEW);
        if(Build.VERSION.SDK_INT>=24) { //判读版本是否在7.0以上
            Uri apkUri =
                    FileProvider.getUriForFile(mContext, "com.qh.qh2298.provider",  apkfile);
            //添加这一句表示对目标应用临时授权该Uri所代表的文件
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            i.setDataAndType(apkUri, "application/vnd.android.package-archive");
        }else {
            i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive");
        }
        mContext.startActivity(i);
		//退出软件
		System.exit(0);	
	}

}
